#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>

using namespace std;

//vfork  clone
//其中clone的选项十分复杂，需要自己传子进程的栈，tid，关联父进程的pid
// clone的作用是用户指定某个子进程继承或拷贝父进程的某些特定资源，如信号量，内存，文件描述符，文件系统等

// vfork是和父进程共享资源，只有子进程exit或者exec替换后，父进程才会继续运行，子进程return也是不行
// vfork和fork的区别是fork会发生写时拷贝，自己另开一个空间存储。而vfork更像线程一样，只是父进程的一个执行流
int gobal = 10;
int main()
{
    int local_1 = 20;

    pid_t id = vfork();//注意：vfork后 父进程直接阻塞，这样在其后面定义的的变量在子进程修改过后又被定义覆盖了一遍，故父进程的值依然不变
    // pid_t id = fork();

    int local_2 = 30;//至于为什么没有重复定义问题，因为下面这个变量是子进程入栈的，子进程exit后会自己pop掉，父进程进来便又创建了
    int cnt = 3;
    if (id == 0)
    {
        // 进入子进程
        while (cnt--)
        {
            sleep(1);
            cout << "子进程正在工作pid：" << getpid() << " cnt 的值：" << cnt << endl;
        }
        gobal = 100;
        local_1 = 200;
        local_2 = 300;

        // return 0;
        cout << "在子进程中 gobal = " << gobal << " "
             << "local_1 = " << local_1 <<" local_2 = " << local_2 << endl;

        //程序替换
        // execlp("ls","ls","-a","-l",nullptr);
        exit(1);
        //return 会报错

    }
    // 父进程
    cout << "创建子进程成功id是：" << id << endl;
    pid_t exitid = waitpid(id, nullptr, 0);
    // if (exitid > 0)
    //     cout << "子进程回收成功"
    //          << "父进程的pid： " << getpid() << endl; // vfork也需要回收

    cout << "打印cnt的数：" << cnt << endl;
    cout << "在父进程中 gobal = " << gobal << " "
         << "local_1 = " << local_1 <<" local_2 = " << local_2 << endl;

    return 0;
}